package com.desay.pangoo.itmt.controller;

import java.io.IOException;
import java.util.*;

import javax.servlet.http.HttpServletResponse;

import com.desay.pangoo.itmt.config.TechOnlineReviewSchedule;
import com.desay.pangoo.itmt.repository.TechOnlineReviewRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.desay.pangoo.common.lite.lang.web.BusinessException;
import com.desay.pangoo.common.lite.lang.web.CommonResponse;
import com.desay.pangoo.common.lite.lang.web.CustomException;
import com.desay.pangoo.itmt.constants.Constant;
import com.desay.pangoo.itmt.controller.vo.TechOnlineReviewAttendVo;
import com.desay.pangoo.itmt.controller.vo.TechOnlineReviewRelevantVo;
import com.desay.pangoo.itmt.controller.vo.TechOnlineReviewTMTVo;
import com.desay.pangoo.itmt.controller.vo.TechOnlineReviewVo;
import com.desay.pangoo.itmt.entity.TechOnlineReviewEntity;
import com.desay.pangoo.itmt.entity.TechOnlineReviewRelevantEntity;
import com.desay.pangoo.itmt.entity.TechOnlineReviewTMTEntity;
import com.desay.pangoo.itmt.enums.ExceptionCodeEnum;
import com.desay.pangoo.itmt.repository.TechOnlineReviewRelevantRepository;
import com.desay.pangoo.itmt.repository.TechOnlineReviewTMTRepository;
import com.desay.pangoo.itmt.repository.spec.ExpandCriteria;
import com.desay.pangoo.itmt.repository.spec.Restrictions;
import com.desay.pangoo.itmt.service.TechOnLineReviewService;
import com.desay.pangoo.itmt.utils.ExportUtil;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HtmlUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 数据集
 *
 * @author uidq1163
 */
@RestController
@Api(tags = "技术在线审批流程管理")
@RequestMapping(value = "/onlineReview")
@Slf4j
public class TechOnlineReviewController {

	@Autowired
	private TechOnLineReviewService techOnLineReviewService;
	@Autowired
	private TechOnlineReviewRepository techOnlineReviewRepository;
	@Autowired
	private TechOnlineReviewSchedule techOnlineReviewSchedule;

	@GetMapping(value = "")
	@ApiOperation(value = "获取提案申请信息列表", notes = "获取提案申请信息列表")
	@ApiImplicitParams({ @ApiImplicitParam(name = "pageNo", type = "int", value = "指定查询页数", paramType = "query"),
			@ApiImplicitParam(name = "pageSize", type = "int", value = "每页数据数量", paramType = "query"),
			@ApiImplicitParam(name = "isCross", value = "是否跨域:true是，false否", dataTypeClass = Boolean.class, paramType = "query"),
			@ApiImplicitParam(name = "isDisruptive", value = "是否颠覆性技术:true是，false否", dataTypeClass = Boolean.class, paramType = "query"),
			@ApiImplicitParam(name = "reviewResult", value = "评审结果：true通过，false不通过", dataTypeClass = Boolean.class, paramType = "query"),
			@ApiImplicitParam(name = "reviewProcess", value = "评审状态：done评审完成，ongoing评审中", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "proposalName", value = "提案名称（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "creator", value = "提案申请者（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "subsidiary", value = "子技术（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "description", value = "描述（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "techLevel", value = "技术等级", dataTypeClass = Integer.class, paramType = "query"),
			@ApiImplicitParam(name = "roadMap", value = "技术路线（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "ptn", value = "技术编号", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "workGroupId", value = "工作组分类ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "reviewType", value = "评审类型:技术规划评审:1，技术定义与研究任务书评审:2，技术成果交付评审:3",allowMultiple = true, dataTypeClass = List.class, paramType = "query"),
			@ApiImplicitParam(name = "startDueDate", value = "到期时间：开始", dataTypeClass = Date.class, paramType = "query"),
			@ApiImplicitParam(name = "endDueDate", value = "到期时间结果", dataTypeClass = Date.class, paramType = "query"),
			@ApiImplicitParam(name = "responsible",value = "责任人",dataTypeClass = Set.class, paramType = "query"),
			@ApiImplicitParam(name = "isPlReview",value = "PLTMT技术课题注册的技术交付申请:1-是,0否",dataTypeClass = Boolean.class, paramType = "query")

	})
	public ResponseEntity<Object> getAllList(@RequestParam(value = "workGroupId", required = false) Long workGroupId,
			@RequestParam(value = "isCross", required = false) Boolean isCross,
			@RequestParam(value = "ptn", required = false) String ptn,
			@RequestParam(value = "isDisruptive", required = false) Boolean isDisruptive,
			@RequestParam(value = "reviewResult", required = false) Boolean reviewResult,
			@RequestParam(value = "reviewProcess", required = false) String reviewProcess,
			@RequestParam(value = "creator", required = false) String creator,
			@RequestParam(value = "proposalName", required = false) String proposalName,
			@RequestParam(value = "subsidiary", required = false) String subsidiary,
			@RequestParam(value = "description", required = false) String description,
			@RequestParam(value = "techLevel", required = false) Integer techLevel,
			@RequestParam(value = "roadMap", required = false) String roadMap,
			@RequestParam(value = "startDueDate", required = false) Date startDueDate,
			@RequestParam(value = "endDueDate", required = false) Date endDueDate,
			@RequestParam(value = "reviewType", required = false) List<Integer> reviewType,
			@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
			@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
		 	@RequestParam(value = "responsible",required = false) Set<String> responsible,
		 	@RequestParam(value = "isPlReview", required = false) Boolean isPlReview,
		    @RequestParam(value = "finalTechnologyLeadership",required = false) Integer finalTechnologyLeadership,
			@RequestParam(value = "finalTechnologyContribution",required = false)Integer finalTechnologyContribution) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.getList(ptn, reviewProcess,
				reviewType, workGroupId, isCross, creator, isDisruptive, reviewResult, proposalName, subsidiary,
				description, techLevel, roadMap, startDueDate, endDueDate, pageNo, pageSize, responsible,isPlReview,finalTechnologyLeadership,finalTechnologyContribution)), HttpStatus.OK);
	}

	@PostMapping(value = "")
	@ApiOperation(value = "添加申请", notes = "添加申请")
	public ResponseEntity<Object> create(@RequestBody TechOnlineReviewVo vo) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.create(vo)), HttpStatus.OK);
	}

	@PostMapping(value = "createCalendar")
	@ApiOperation(value = "手动添加日历", notes = "手动添加日历(如果日历存在就更新日程信息)")
	public ResponseEntity<Object> createCalendars(@RequestParam Long id) {
		Optional<TechOnlineReviewEntity> option = techOnlineReviewRepository.findById(id);
		TechOnlineReviewEntity entity = option.get();
		if (entity.getEventId() == null) {
			techOnlineReviewSchedule.createCalendars(null, entity);
		}
		List<TechOnlineReviewTMTEntity> listTmts = techOnlineReviewTMTRepository.findByTechOnlineReview(entity);
		// 添加参会人员到日程信息
		List<String> ids = listTmts.stream().map(TechOnlineReviewTMTEntity::getTmtUser).toList();
		techOnlineReviewSchedule.updateCalendars(entity.getEventId(), null, ids);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@PutMapping(value = "{id}")
	@ApiOperation(value = "编辑申请", notes = "更新申请")
	public ResponseEntity<Object> update(@PathVariable(value = "id") Long id, @RequestBody TechOnlineReviewVo vo) {
		techOnLineReviewService.update(id, vo);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@PutMapping(value = "pushMail/{id}")
	@ApiOperation(value = "手动推送提案申请邮件", notes = "手动推送提案申请邮件")
	public ResponseEntity<Object> pushMail(@PathVariable(value = "id") Long id) {
		techOnLineReviewService.pushMail(id);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@GetMapping(value = "{id}")
	@ApiOperation(value = "根据id获取申请详细信息", notes = "根据id获取申请详细信息")
	public ResponseEntity<Object> getInfoById(@PathVariable(value = "id") Long id) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.getInfoById(id)), HttpStatus.OK);
	}

	@GetMapping(value = "relevant/{id}")
	@ApiOperation(value = "根据提案id获取ITMT申请反馈信息", notes = "根据提案id获取ITMT申请反馈信息")
	public ResponseEntity<Object> getRelevantInfoById(@PathVariable(value = "id") Long id) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.getRelevantInfoById(id)),
				HttpStatus.OK);
	}

	@PostMapping(value = "relevant")
	@ApiOperation(value = "提案申请相关性反馈", notes = "提案申请相关性反馈")
	public ResponseEntity<Object> relevant(
			@RequestParam(value = "isAdmin", defaultValue = "false", required = false) Boolean isAdmin,
			@RequestBody TechOnlineReviewRelevantVo vo) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.relevant(isAdmin, vo)),
				HttpStatus.OK);
	}

	@PostMapping(value = "review/tmt")
	@ApiOperation(value = "TMT反馈", notes = "TMT反馈")
	public ResponseEntity<Object> tmtReview(@RequestBody TechOnlineReviewTMTVo vo) {
		techOnLineReviewService.tmtReview(vo);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@GetMapping(value = "review/{id}")
	@ApiOperation(value = "获取TMT反馈列表信息", notes = "获取TMT反馈列表信息")
	public ResponseEntity<Object> getTmtReviewList(@PathVariable(value = "id", required = true) Long id) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.getTmtReviewList(id)),
				HttpStatus.OK);
	}

	@GetMapping(value = "reviewResult/{id}")
	@ApiOperation(value = "获取TMT反馈结果信息", notes = "获取TMT反馈结果信息")
	public ResponseEntity<Object> getTmtReviewResult(@PathVariable(value = "id", required = true) Long id) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.participateRateInfo(id)),
				HttpStatus.OK);
	}

	@PostMapping(value = "/files")
	@ApiOperation(value = "文件上传")
	public ResponseEntity<Object> upload(MultipartFile[] multipartFile,
			@RequestParam(value = "fileType", required = false) String fileType) {
		try {
			return new ResponseEntity<>(
					CommonResponse.success(techOnLineReviewService.uploadFile(multipartFile, fileType)), HttpStatus.OK);
		} catch (CustomException e) {
			log.error("{}", e);
			// 业务异常直接抛出去
			throw e;
		} catch (IOException e) {
			log.error("{}", e);
			throw new BusinessException(ExceptionCodeEnum.UPLOAD_FILE_ERROR);
		}
	}

	@GetMapping(value = "/file/list")
	@ApiOperation(value = "获取文件列表")
	public ResponseEntity<Object> getFileByFileType(
			@RequestParam(value = "fileType", required = true) String fileType) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.getFileList(fileType)),
				HttpStatus.OK);

	}

	@DeleteMapping(value = "/file/{fileId}")
	@ApiOperation(value = "删除上传")
	public ResponseEntity<Object> deleteFileById(@PathVariable(value = "fileId") Long fileId) {
		techOnLineReviewService.deleteFile(fileId);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);

	}

	@GetMapping(value = "/file/{fileId}")
	@ApiOperation(value = "下载文件")
	public void getFileById(@PathVariable(value = "fileId") Long fileId, HttpServletResponse resp) {
		techOnLineReviewService.downloadFile(fileId, resp);
	}

	@PostMapping(value = "review/attend")
	@ApiOperation(value = "更新TMT参会情况，只有参会的成员才有资格评审,同时开启评审权限", notes = "更新TMT参会情况，只有参会的成员才有资格评审")
	public ResponseEntity<Object> updateTmtAttendReviewMeeting(@RequestBody TechOnlineReviewAttendVo vo) {
		techOnLineReviewService.updateTmtAttendReviewMeeting(vo);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@PostMapping(value = "review/openView/{id}")
	@ApiOperation(value = "评审开始", notes = "评审开始：提案人触发，消息通知参会人员参与评审")
	public ResponseEntity<Object> updateViewStatus(@PathVariable(value = "id") Long id) {
		techOnLineReviewService.openView(id);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@GetMapping(value = "review/history")
	@ApiOperation(value = "获取历史评审记录", notes = "获取历史评审记录")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "reviewType", value = "评审类型:技术规划评审:1，技术定义与研究任务书评审:2，技术成果交付评审:3", required = true, dataType = "int", paramType = "query"),
			@ApiImplicitParam(name = "techId", value = "技术课题项目Id", dataType = "int", allowMultiple = true, paramType = "query") })
	public ResponseEntity<Object> getHistoryList(Integer reviewType,
			@RequestParam(value = "techId") List<Long> techId) {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.getHistoryList(reviewType, techId)),
				HttpStatus.OK);
	}

	@GetMapping(value = "review/expertReviewList")
	@ApiOperation(value = "TMT专家评审榜单", notes = "获取评审人员记录:participate：null-未参会， participate：false-参会弃权评审，participate： true-参会")
	public ResponseEntity<Object> countExpertRviewListTmtInfo() {
		return new ResponseEntity<>(CommonResponse.success(techOnLineReviewService.countExpertRviewListTmtInfo()),
				HttpStatus.OK);
	}

	@GetMapping(value = "review/monthlyProgressChart")
	@ApiOperation(value = "技术评审月度推移图", notes = "管理看板【技术评审月度推移图】，月度数据（已评审完成时间为准）（可选年份），规划/定义/交付三类，通过/不通过数量的堆积柱状图")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "year", value = "可选年份(yyyy)", required = false, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "reviewType", value = "评审类型:技术规划评审:1，技术定义与研究任务书评审:2，技术成果交付评审:3", required = false, dataType = "int", paramType = "query"), })
	public ResponseEntity<Object> technicalreviewMonthlyProgressChart(
			@RequestParam(value = "year", required = false) String year,
			@RequestParam(value = "reviewType", required = false) Integer reviewType) {
		return new ResponseEntity<>(
				CommonResponse.success(techOnLineReviewService.monthlyProgressChart(year, reviewType)), HttpStatus.OK);
	}

	@Autowired
	private TechOnlineReviewTMTRepository techOnlineReviewTMTRepository;

	@GetMapping(value = "review/export", headers = "Accept=application/octet-stream")
	@ApiOperation(value = "评审结论导出", notes = "")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "reviewType", value = "评审类型:技术规划评审:1，技术定义与研究任务书评审:2，技术成果交付评审:3", required = false, dataType = "int", paramType = "query"), })
	public void exportExcel(HttpServletResponse response,
			@RequestParam(value = "reviewType", required = false) Integer reviewType) throws IOException {
		ExpandCriteria<TechOnlineReviewTMTEntity> c = new ExpandCriteria<>();
		// 根据组查询
		c.add(Restrictions.eq("techOnlineReview.reviewType", reviewType, true));
		// 已经评审结束
		c.add(Restrictions.isNotNull("techOnlineReview.reviewResult"));
		ExportUtil<TechOnlineReviewTMTEntity> exportUtil = new ExportUtil<>(techOnlineReviewTMTRepository, c);
		exportUtil.export("评审结论导出", response, this::process);
	}

	/**
	 * 指定表头信息和内容
	 *
	 * @param objMap
	 * @return
	 */
	private Map<String, Object> process(TechOnlineReviewTMTEntity objMap) {
		Map<String, Object> row = new LinkedHashMap<>();
		TechOnlineReviewEntity reviewEntity = objMap.getTechOnlineReview();
		row.put("提案人", reviewEntity.getCreator());
		row.put("提案时间", DateUtil.format(reviewEntity.getCreateTime(), "yyyy-MM-dd"));
		row.put("评审时间", DateUtil.format(objMap.getModifyTime(), "yyyy-MM-dd"));
		row.put("提案主域", reviewEntity.getWorkGroup().getWorkGroupName());
		switch (reviewEntity.getReviewType()) {
		case 1:
			row.put("评审类型", "技术规划评审");
			break;
		case 2:
			row.put("评审类型", "技术定义与研究任务书评审");
			break;
		case 3:
			row.put("评审类型", "技术成果交付评审");
			break;
		default:
			row.put("评审类型", "");
			break;
		}
		row.put("提案名称", reviewEntity.getProposalName());
		if (null != objMap.getWorkGroup()) {
			row.put("评审人域", objMap.getWorkGroup().getWorkGroupName());
		} else {
			row.put("评审人域", "");
		}
		row.put("评审人", objMap.getTmtFullUser());
		if (objMap.getJudgesType() == 2) {
			row.put("是否参与评审", "旁听");
		} else {
			row.put("是否参与评审", objMap.getIsParticipate() == null ? "未参会弃权"
					: Boolean.TRUE.equals(objMap.getIsParticipate()) ? "参与评审" : "参会弃权");
		}
		if (null != objMap.getIsPassed()) {
			row.put("通过", objMap.getIsPassed() ? "是" : "否");
		} else {
			row.put("通过", "");
		}
		try {
			JSONObject jSONObject = JSON.parseObject(objMap.getReviewContent());
			if (null != jSONObject && jSONObject.containsKey(Constant.JSON_STR)
					&& null != jSONObject.getString(Constant.JSON_STR)) {
				String reviewContent = HtmlUtil.cleanHtmlTag(jSONObject.getString(Constant.JSON_STR));
				row.put("评审意见", reviewContent);
			} else {
				row.put("评审意见", objMap.getReviewContent());
			}
		} catch (Exception e) {
			row.put("评审意见", objMap.getReviewContent());
		}
		return row;
	}

	@Autowired
	TechOnlineReviewRelevantRepository techOnlineReviewRelevantRepository;

	@GetMapping(value = "relevant/export", headers = "Accept=application/octet-stream")
	@ApiOperation(value = "相关性反馈导出", notes = "")
	public void exportRelevantExcel(HttpServletResponse response,
			@RequestParam(value = "reviewType", required = false) Integer reviewType) throws IOException {
		ExpandCriteria<TechOnlineReviewRelevantEntity> c = new ExpandCriteria<>();
		ExportUtil<TechOnlineReviewRelevantEntity> exportUtil = new ExportUtil<>(techOnlineReviewRelevantRepository, c);
		exportUtil.export("相关性反馈导出", response, this::processRelevant);
	}

	/**
	 * 指定表头信息和内容
	 *
	 * @param objMap
	 * @return
	 */
	private Map<String, Object> processRelevant(TechOnlineReviewRelevantEntity objMap) {
		Map<String, Object> row = new LinkedHashMap<>();
		TechOnlineReviewEntity reviewEntity = objMap.getTechOnlineReview();
		row.put("提案名称", reviewEntity.getProposalName());
		row.put("提案人", reviewEntity.getCreator());
		row.put("提案时间", DateUtil.format(reviewEntity.getCreateTime(), "yyyy-MM-dd"));
		// TMT相关性反馈期限
		row.put("相关性反馈截至日期", DateUtil.format(reviewEntity.getTmtReviewDueDate(), "yyyy-MM-dd"));
		// 评审会时间
		row.put("评审会时间", DateUtil.format(reviewEntity.getReviewDate(), "yyyy-MM-dd"));
		row.put("提案主域", reviewEntity.getWorkGroup().getWorkGroupName());
		// TMT实际反馈时间
		row.put("TMT实际反馈时间", DateUtil.format(objMap.getCreateTime(), "yyyy-MM-dd"));
		//
		row.put("TMT实际周期（天）", DateUtil.between(reviewEntity.getCreateTime(), objMap.getCreateTime(), DateUnit.DAY));

		return row;
	}


}
